#pragma once
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include "PokerHands.h"
using namespace std;

#define CALCULATE_STRENGTH_LOOP 1000
static const CardType POKER_CARDS[] =
{
    0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, //方块
    0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, 0x020C, 0x020D, 0x020E, //梅花
    0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, //红桃
    0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E  //黑桃
};

static const int BOARD_NUM[] = {0, 0, 3, 4, 5}; //阶段对应的公共牌数量

static const int CARD_NUM = sizeof(POKER_CARDS) / sizeof(CardType);
static const int MAX_RAND_NUM = 9;

unsigned static randoms(unsigned l, unsigned h)
{
    unsigned r = rand();
    return r % (h - l + 1) + l;
}

static int cmp_hands(const CardType *hands1, const CardType *hands2, const CardType *board)
{
    //check_not_equal(hands1, hands2, board);
    CardType handcard1[5];
    CardType handcard2[5];
    CPokerHands calculater;
    calculater.SetHands(hands1[0], hands1[1], board);
    calculater.CheckHandsType(handcard1);
    unsigned char type1 = calculater.GetHandsType();
    calculater.Initialize();
    calculater.SetHands(hands2[0], hands2[1], board);
    calculater.CheckHandsType(handcard2);
    unsigned char type2 = calculater.GetHandsType();
    return CompHandsType(type1, handcard1, type2, handcard2);
}


class Poker
{
public:
    Poker()
    {
        memset(m_isused, 0, sizeof(m_isused));
        m_used_num = 0;
        m_idx = 0;
    }
    void deal_cards(CardType *cards, int num) //发出num张牌
    {
        if (cards == NULL)
            return;
        sort(cards, cards + num);
        int j = 0;
        for (int i = 0; i < CARD_NUM; ++i)
        {
            if (j == num)
                break;
            if (POKER_CARDS[i] == cards[j])
            {
                m_isused[i] = true;
                ++m_used_num;
                ++j;
            }
        }
    }
    const CardType *rand_cards2(int num) //在当前牌堆中随机获取num张牌
    {
        CardType *ret = &m_rand_cards[m_idx];
        if (num > MAX_RAND_NUM)
            return NULL;
        int rand_num[MAX_RAND_NUM];
        int len = 0;
        for (int i = 0; i < num; ++i) //找出num个1到CARD_NUM-m_used_num的随机数
        {
            rand_num[len] = randoms(0, CARD_NUM - m_used_num - len - 1);

            for (int j = 0; j < len; ++j) //找会原来的索引
            {
                if (rand_num[j] >= rand_num[len])
                    ++rand_num[len];
            }
            ++len;
        }
        sort(rand_num, rand_num + len);

        //从m_rand_cards中取出这num张牌
        int offset = 0;
        int n = 0; //索引rand_num
        for (int i = 0; i < CARD_NUM; ++i)
        {
            if (m_isused[i])
            {
                int idx = rand_num[n] + offset; //在[0,52)的idx
                while (n < len && idx < i)
                {
                    m_isused[idx] = true;
                    ++m_used_num;
                    m_rand_cards[m_idx++] = POKER_CARDS[idx];
                    idx = rand_num[++n] + offset;
                }
                ++offset;
            }
        }

        {
            int idx = rand_num[n] + offset;
            while (n < len && idx < CARD_NUM)
            {
                m_isused[idx] = true;
                ++m_used_num;
                m_rand_cards[m_idx++] = POKER_CARDS[idx];
                idx = rand_num[++n] + offset;
            }
        }
        return ret;
    }
    const CardType *rand_cards(int num)
    {
        int n = 0;
        if (num > MAX_RAND_NUM)
            return NULL;
        CardType *ret = &m_rand_cards[m_idx];
        while (n < num)
        {
            int r = randoms(0, CARD_NUM - 1);
            if (m_isused[r])
                continue;
            m_isused[r] = true;
            ++m_used_num;
            m_rand_cards[m_idx++] = POKER_CARDS[r];
            ++n;
        }
        return ret;
    }
    void print()
    {
        sort(m_rand_cards, m_rand_cards + m_idx);
        for (int i = 0; i < m_idx - 1; ++i)
            assert(m_rand_cards[i] != m_rand_cards[i + 1]);
        for (int i = 0; i < m_idx; ++i)
            printf("%x ", m_rand_cards[i]);
        printf("\n");
    }

private:
    CardType m_rand_cards[MAX_RAND_NUM]; //随机发出的牌
    int m_idx;
    bool m_isused[CARD_NUM]; //已被发出的牌
    int m_used_num;
};


